# -*- mode: python -*-

from site_scons.mongo import insort_wrapper

Import(
    [
        "endian",
        "env",
        "use_libunwind",
        "use_system_version_of_library",
        "version_extra",
        "version_parts",
    ]
)

env = env.Clone()

env.InjectThirdParty("asio")

if env.TargetOSIs("windows"):
    enterpriseEnv = env.Clone().InjectModule("enterprise")
    generatedResourceConstantFile = enterpriseEnv.Substfile(
        "resource_constants.h.in",
        SUBST_DICT=[
            ("@mongo_version@", env["MONGO_VERSION"]),
            ("@mongo_version_major@", version_parts[0]),
            ("@mongo_version_minor@", version_parts[1]),
            ("@mongo_version_patch@", version_parts[2]),
            ("@mongo_git_hash@", env["MONGO_GIT_HASH"]),
        ],
    )
    env.Alias("generated-sources", generatedResourceConstantFile)

env.SConscript(
    must_exist=1,
    dirs=[
        "concurrency",
        "cryptd",
        "immutable",
        "net",
        "options_parser",
        "tracing_profiler",
        "tracking",
    ],
    exports=[
        "env",
        "version_extra",
        "version_parts",
    ],
)

env.Benchmark(
    target="fail_point_bm",
    source=[
        "fail_point_bm.cpp",
    ],
    LIBDEPS=[
        "fail_point",
    ],
)

env.CppUnitTest(
    target="concurrent_shared_values_map_test",
    source=[],
    LIBDEPS=[],
    PROVE_ALIASES=["server-programmability"],
)

env.CppUnitTest(
    target="tracing_support_test",
    source=[],
    LIBDEPS=[],
)

env.CppUnitTest(
    target="thread_safety_context_test",
    source=[],
    LIBDEPS=[],
    PROVE_ALIASES=["server-programmability"],
)

env.CppUnitTest(
    target="versioned_value_test",
    source=[],
    LIBDEPS=[],
    PROVE_ALIASES=["server-programmability"],
)

tcmallocAttrs = None
for impl in [
    {
        # Modern standalone tcmalloc (not gperftools)
        "options": ["tcmalloc-google"],
        "sys_name": "tcmalloc-google",
        "inject": "tcmalloc",
        "cppdefs": [],
    },
    {
        # Old gperftools tcmalloc
        "options": ["tcmalloc-gperf"],
        "sys_name": "tcmalloc-gperf",
        "inject": "gperftools",
        # If our changes to tcmalloc are ever upstreamed, this should become set based on a top
        # level configure check, though its effects should still be scoped just to these files.
        "cppdefs": [
            "MONGO_HAVE_GPERFTOOLS_SIZE_CLASS_STATS",
        ],
    },
]:
    if env["MONGO_ALLOCATOR"] in impl["options"]:
        tcmallocAttrs = impl

if tcmallocAttrs:
    tcmspEnv = env.Clone()
    if not use_system_version_of_library(tcmallocAttrs["sys_name"]):
        tcmspEnv.InjectThirdParty(tcmallocAttrs["inject"])
    tcmspEnv.Append(CPPDEFINES=tcmallocAttrs["cppdefs"])

    if tcmspEnv.ToolchainIs("clang", "GCC"):
        tcmspEnv.Append(CCFLAGS=["-Wno-sign-compare"])

    if not use_system_version_of_library("valgrind"):
        # Include valgrind since tcmalloc disables itself while running under valgrind
        tcmspEnv.InjectThirdParty("valgrind")

    tcmspEnv.CppUnitTest(
        target="tcmalloc_set_parameters_test",
        source=[
            "tcmalloc_set_parameter_test.cpp",
        ],
        LIBDEPS=[
            "$BUILD_DIR/mongo/db/commands/server_status_core",
            "$BUILD_DIR/mongo/db/server_base",
            "processinfo",
            "tcmalloc_server_status",
            "tcmalloc_set_parameter",
        ],
    )

env.Benchmark(
    target="clock_source_bm",
    source=[
        "clock_source_bm.cpp",
    ],
    LIBDEPS=[
        "clock_sources",
        "processinfo",
    ],
    CONSOLIDATED_TARGET="first_half_bm",
)

env.CppUnitTest(
    target="executor_stats_test",
    source=[
        "executor_stats_test.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/util/clock_source_mock",
        "$BUILD_DIR/mongo/util/executor_stats",
    ],
    PROVE_ALIASES=["server-programmability"],
)

env.Benchmark(
    target="decimal_counter_bm",
    source=[
        "decimal_counter_bm.cpp",
    ],
    LIBDEPS=[],
    CONSOLIDATED_TARGET="first_half_bm",
)

env.Benchmark(
    target="itoa_bm",
    source=[
        "itoa_bm.cpp",
    ],
    LIBDEPS=[],
)

env.Benchmark(
    target="future_bm",
    source=[
        "future_bm.cpp",
    ],
    LIBDEPS=[],
)

env.Benchmark(
    target="tick_source_bm",
    source=[
        "tick_source_bm.cpp",
    ],
    LIBDEPS=[],
    CONSOLIDATED_TARGET="first_half_bm",
)

pcre_env = env.Clone()
pcre_env.InjectThirdParty(libraries=["pcre2"])

env.Benchmark(
    target="hash_table_bm",
    source="hash_table_bm.cpp",
    LIBDEPS=[],
)

icuEnv = env.Clone()

if not use_system_version_of_library("icu"):
    icuEnv.InjectThirdParty("icu")
    # Since we are injecting the third-party ICU headers, we must also copy the same defines that we
    # use to configure ICU when building ICU sources. See comment in
    # src/third_party/icu4c-57.1/source/SConscript.
    icuEnv.Append(
        CPPDEFINES=[
            ("UCONFIG_NO_BREAK_ITERATION", 1),
            ("UCONFIG_NO_FORMATTING", 1),
            ("UCONFIG_NO_TRANSLITERATION", 1),
            ("UCONFIG_NO_REGULAR_EXPRESSIONS", 1),
            ("U_CHARSET_IS_UTF8", 1),
            ("U_STATIC_IMPLEMENTATION", 1),
            ("U_USING_ICU_NAMESPACE", 0),
        ],
    )


icuEnv.CppUnitTest(
    target="util_test",
    source=[],
    LIBDEPS=[],
    PROVE_ALIASES=["server-programmability"],
)

if not env.TargetOSIs("windows"):
    icuEnv.CppUnitTest(
        target="signal_handlers_test",
        source=[
            "signal_handlers_asynchronous_test.cpp",
            "signal_handlers_synchronous_test.cpp",
        ],
        LIBDEPS=[
            "$BUILD_DIR/mongo/base",
            "$BUILD_DIR/mongo/db/service_context_non_d",
            "signal_handlers",
            "version_impl",
        ],
        PROVE_ALIASES=["server-programmability"],
    )

if env.TargetOSIs("windows"):
    env.CppUnitTest(
        target="util_windows_test",
        source=[
            "ntservice_test.cpp",
            "perfctr_collect_test.cpp",
        ],
        LIBDEPS=[
            "ntservice",
            "perfctr_collect",
        ],
        LIBS=[
            "shell32",
            env["LIBS"],
        ],
    )

env.Benchmark(target="base64_bm", source="base64_bm.cpp", CONSOLIDATED_TARGET="first_half_bm")

stacktraceEnv = env.Clone()
if use_libunwind:
    stacktraceEnv.InjectThirdParty(libraries=["unwind"])
    stacktraceEnv.CppUnitTest(
        target=[
            "stacktrace_libunwind_test",
        ],
        source=[
            "stacktrace_libunwind_test_functions.cpp",
            "stacktrace_libunwind_test.cpp",
        ],
        PROVE_ALIASES=["server-programmability"],
        # Do not add LIBDEPS the ordinary way here, as they will override
        # the LIBDEPS settings for stacktraceEnv, configured above. If
        # you must add new libdeps here, or for the similar cases
        # below, do it as follows:
        #
        # LIBDEPS=(stacktraceEnv.get('LIBDEPS', []) + [
        #     some_new_libdep,
        #     another_new_libdep,
        # ]),
        #
        # to ensure that the new library dependency is added to the
        # existing LIBDEPS state in the environment and does not
        # overwrite it.
    )

stacktrace_test_LIBDEPS = stacktraceEnv.get("LIBDEPS", []).copy()
insort_wrapper(stacktrace_test_LIBDEPS, "pcre_wrapper")

stacktraceEnv.CppUnitTest(
    target="stacktrace_test",
    source=[
        "stacktrace_test.cpp",
    ],
    LIBDEPS=stacktrace_test_LIBDEPS,
    EXPORT_SYMBOLS=[
        "mongo_stacktrace_test_detail_testFunctionWithLinkage",
    ],
    PROVE_ALIASES=["server-programmability"],
)

stacktraceEnv.Benchmark(
    target="stacktrace_bm",
    source="stacktrace_bm.cpp",
    # See above for how to handle any future LIBDEPS additions here.
    # LIBDEPS=...
)

env.Benchmark(
    target="string_bm",
    source="string_bm.cpp",
)

env.Benchmark(
    target="cancellation_bm",
    source="cancellation_bm.cpp",
)

env.Benchmark(
    target="inline_memory_bm",
    source="inline_memory_bm.cpp",
)

env.Benchmark(
    target="uuid_bm",
    source=[
        "uuid_bm.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
        "processinfo",
    ],
    CONSOLIDATED_TARGET="first_half_bm",
)

pretty_printer_test_program = env.Program(
    target="pretty_printer_test_program",
    source=[
        "pretty_printer_test_program.cpp",
    ],
    LIBDEPS=[
        "$BUILD_DIR/mongo/base",
    ],
    AIB_COMPONENT="pretty-printer-tests",
    AIB_COMPONENTS_EXTRA=["dist-test"],
)
pretty_printer_test_program_installed = env.GetAutoInstalledFiles(pretty_printer_test_program[0])

env.PrettyPrinterTest("pretty_printer_test.py", TEST_PROGRAM=pretty_printer_test_program_installed)
